﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data;
using System.Collections;

namespace System
{
    /// <summary>
    /// DataBinding extension methods
    /// </summary>
    public static class BindingExt
    {
        /// <summary>
        /// Sets control property from datasource even if control is not created yet.
        /// </summary>
        /// <param name="binding">The binding.</param>
        public static void ForceReadValue(this Binding binding)
        {
            if (!binding.Control.Created)
            {
                try
                {
                    object bindToObject = binding.GetFieldValue("bindToObject");
                    object value = bindToObject.RunMethod("GetValue");
                    if (value is DataRowView)
                        value = (value as DataRowView)[binding.BindingMemberInfo.BindingField];
                    binding.Control.SetPropertyValue(binding.PropertyName, value);
                }
                catch (Exception ex)
                {
                    ex.LogInternal();
                }
            }
            else
                binding.ReadValue();
        }
        /// <summary>
        /// Reads the value from binding.
        /// </summary>
        /// <param name="c">The c.</param>
        /// <param name="childControls">if set to <c>true</c> [child controls].</param>
        public static void ReadValueFromBinding(this Control c, bool childControls)
        {
            foreach (Binding b in c.DataBindings)
                b.ForceReadValue();
            if (childControls)
            {
                foreach (Control c2 in c.Controls)
                    c2.ReadValueFromBinding(childControls);
            }
        }

        /// <summary>
        /// Reads the values from bindings.
        /// </summary>
        /// <param name="manager">The manager.</param>
        /// <param name="onlyNotCreatedControls">if set to <c>true</c> [only not created controls].</param>
        public static void ReadValuesFromBindings(this BindingManagerBase manager, bool onlyNotCreatedControls = false)
        {
            if (manager != null)
            {
                try
                {
                    Binding[] bindings = new Binding[manager.Bindings.Count];
                    manager.Bindings.CopyTo(bindings, 0);
                    foreach (Binding b in bindings)
                    {
                        if (!onlyNotCreatedControls || !b.Control.Created)
                            b.ForceReadValue();
                    }
                }
                catch (Exception ex)
                {
                    ex.LogInternal();
                }
            }
        }
        /// <summary>
        /// Reads the values from bindings.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="onlyNotCreatedControls">if set to <c>true</c> [only not created controls].</param>
        public static void ReadValuesFromBindings(this BindingContext context, bool onlyNotCreatedControls = false)
        {
            if (context != null)
            {
                try
                {
                    IEnumerable enumerable = context as IEnumerable;
                    IEnumerator enumerator = enumerable.GetEnumerator();
                    DictionaryEntry entry;
                    object target;
                    if (enumerator != null)
                    {
                        while (enumerator.MoveNext())
                        {
                            if (enumerator.Current is BindingManagerBase)
                            {
                                (enumerator.Current as BindingManagerBase).ReadValuesFromBindings(onlyNotCreatedControls);
                            }
                            else if (enumerator.Current is DictionaryEntry)
                            {
                                entry = (DictionaryEntry)(enumerator.Current);
                                target = entry.Value.GetPropertyValue("Target");
                                if (target is BindingManagerBase)
                                {
                                    (target as BindingManagerBase).ReadValuesFromBindings(onlyNotCreatedControls);
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    ex.LogInternal();
                }
            }
        }
        /// <summary>
        /// Reads the values from bindings.
        /// </summary>
        /// <param name="control">The control.</param>
        /// <param name="dataSource">The data source.</param>
        /// <param name="dataMember">The data member.</param>
        /// <param name="onlyNotCreatedControls">if set to <c>true</c> [only not created controls].</param>
        public static void ReadValuesFromBindings(this ContainerControl control, object dataSource, string dataMember = "", bool onlyNotCreatedControls = false)
        {
            if (control != null && control.BindingContext != null)
            {
                try
                {
                    control.BindingContext[dataSource, dataMember].ReadValuesFromBindings(onlyNotCreatedControls);
                }
                catch (Exception ex)
                {
                    ex.LogInternal();
                }
            }
        }
        /// <summary>
        /// Reads the values from bindings.
        /// </summary>
        /// <param name="control">The control.</param>
        /// <param name="onlyNotCreatedControls">if set to <c>true</c> [only not created controls].</param>
        public static void ReadValuesFromBindings(this ContainerControl control, bool onlyNotCreatedControls = false)
        {
            if(control!=null)
                control.BindingContext.ReadValuesFromBindings(onlyNotCreatedControls);
        }
        /// <summary>
        /// Ends the current edit.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="updateNotCreatedControls">if set to <c>true</c> [update not created controls].</param>
        public static void EndCurrentEdit(this BindingContext context, bool updateNotCreatedControls = true)
        {
            if (context != null)
            {
                try
                {
                    IEnumerable enumerable = context as IEnumerable;
                    IEnumerator enumerator = enumerable.GetEnumerator();
                    DictionaryEntry entry;
                    object target;
                    BindingManagerBase manager;
                    if (enumerator != null)
                    {
                        while (enumerator.MoveNext())
                        {
                            manager = null;
                            if (enumerator.Current is BindingManagerBase)
                            {
                                manager = (enumerator.Current as BindingManagerBase);
                            }
                            else if (enumerator.Current is DictionaryEntry)
                            {
                                entry = (DictionaryEntry)(enumerator.Current);
                                target = entry.Value.GetPropertyValue("Target");
                                if (target is BindingManagerBase)
                                {
                                    manager = (target as BindingManagerBase);
                                }
                            }
                            if (manager != null)
                            {
                                manager.EndCurrentEdit();
                                if (updateNotCreatedControls)
                                    manager.ReadValuesFromBindings(true);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    ex.LogInternal();
                }
            }
        }
    }
}
